package com.example.server.service.admin.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.BCrypt;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.server.common.config.auth.JwtTokenUtil;
import com.example.server.common.config.auth.TokenUser;
import com.example.server.common.config.exception.BusinessException;
import com.example.server.common.constant.*;
import com.example.server.common.utils.redis.RedisUtil;
import com.example.server.entity.Customer;
import com.example.server.entity.CustomerRole;
import com.example.server.entity.Role;
import com.example.server.mapper.CustomerMapper;
import com.example.server.mapper.CustomerRoleMapper;
import com.example.server.mapper.RoleMapper;
import com.example.server.service.admin.AdminCustomerService;
import com.example.server.service.admin.RoleService;
import com.example.server.vo.StaffVO;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * (User)表服务实现类
 *
 * @author china.fuyao@outlook.com
 * @since 2020-03-25 18:20:48
 */
@Service("adminCustomerService")
public class AdminCustomerServiceImpl extends ServiceImpl<CustomerMapper, Customer> implements AdminCustomerService {

    @Resource
    RedisUtil redisUtil;
    @Resource
    JwtTokenUtil jwtTokenUtil;
    @Resource
    CustomerRoleMapper customerRoleMapper;
    @Resource
    RoleService roleService;

    /**
     * 更新用户登录时间
     *
     * @param customerId
     */
    private boolean updateLastLoginTime(Integer customerId) {
        return this.update(new UpdateWrapper<Customer>().eq("customer_id", customerId).set("last_login_time", LocalDateTime.now()));
    }

    /**
     * @param name
     * @param password
     * @return
     */
    @Override
    public Result login(String name, String password) {
        Customer customer = this.getOne(new QueryWrapper<Customer>().eq("customer_name", name)
                .eq("status", EnableConstants.ENABLE));
        if (null == customer) {
            return Result.Error("用户不存在");
        }
        //判断密码
        boolean checkPassword = BCrypt.checkpw(password, customer.getPassword());
        if (!checkPassword) {
            return Result.Error("用户密码错误");
        }
        //判断用户类型
        if (CustomerConstants.ADMIN_USER != customer.getCustomerType()) {
            return Result.Error("非管理端用户");
        }
        TokenUser tokenUser = new TokenUser();
        tokenUser.setCustomerId(customer.getCustomerId());
        tokenUser.setCustomerName(customer.getCustomerName());
        tokenUser.setStatus(customer.getStatus());
        //获取权限
        tokenUser.setAuthorities(customer.getCustomerType());
        String token = jwtTokenUtil.token(tokenUser);
        LoginResult lr = new LoginResult();
        lr.setCustomerId(customer.getCustomerId());
        lr.setCustomerName(customer.getCustomerName());
        lr.setPhone(customer.getPhone());
        CustomerRole customerRole = customerRoleMapper.selectOne(new QueryWrapper<CustomerRole>().eq("customer_id", customer.getCustomerId())
                .eq("role_type", CustomerConstants.ADMIN_USER));
        lr.setRoleId(customerRole.getRoleId());
        lr.setToken(token);
        lr.setIssuer(TokenConstants.ISSUER_STRING);
        //更新用户登录时间
        updateLastLoginTime(customer.getCustomerId());
        return new Result(lr);
    }

    /**
     * 用户登出
     *
     * @param tokenUser
     * @return
     */
    @Override
    public Result logout(TokenUser tokenUser) {
        //获取旧token
        Object oldToken = redisUtil.get(RedisKey.USER_TOKEN + tokenUser.getCustomerId());
        //清理旧token
        redisUtil.deleteKey(RedisKey.USER_TOKEN + tokenUser.getCustomerId(), RedisKey.TOKEN_USER + oldToken);
        return Result.OK();
    }

    /**
     * 员工列表
     *
     * @param current
     * @param size
     * @param customerId
     * @return
     */
    @Override
    public Result staffList(Integer current, Integer size, String customerName, Integer roleId, Integer customerId) {
        IPage page = new Page(current, size);
        IPage<Map> pageData = baseMapper.staffList(page, customerName, roleId);
        return new Result(pageData);
    }

    /**
     * 新增员工
     *
     * @param staffVO
     * @param customerId
     * @return
     */
    @Override
    @Transactional
    public Result addStaff(StaffVO staffVO, Integer customerId) {
        Customer customer = new Customer();
        customer.setCustomerType(CustomerConstants.ADMIN_USER);
        customer.setCustomerName(staffVO.getCustomerName());
        customer.setPhone(staffVO.getPhone());
        customer.setPassword(BCrypt.hashpw(staffVO.getPassword()));
        customer.setStatus(EnableConstants.ENABLE);
        customer.setAddUid(customerId);
        customer.setAddTime(LocalDateTime.now());
        customer.setUpdateTime(LocalDateTime.now());
        boolean save = save(customer);
        if (save) {
            //增加角色
            Role role = roleService.getById(staffVO.getRoleId());
            CustomerRole customerRole = new CustomerRole();
            customerRole.setCustomerId(customer.getCustomerId());
            customerRole.setRoleId(role.getRoleId());
            customerRole.setRoleType(role.getRoleType());
            int insert = customerRoleMapper.insert(customerRole);
            if (insert > 0) {
                return Result.OK();
            }
        }
        throw new BusinessException("操作失败");
    }

    /**
     * 修改员工
     *
     * @param staffVO
     * @param customerId
     * @return
     */
    @Override
    public Result updateStaff(StaffVO staffVO, Integer customerId) {
        Customer customer = getById(staffVO.getCustomerId());
        if (null == customer) {
            return Result.Error("员工不存在");
        }
        boolean update = update(new UpdateWrapper<Customer>().eq("", staffVO.getCustomerId())
                .set("customer_name", staffVO.getCustomerName()).set("password", BCrypt.hashpw(staffVO.getPassword()))
                .set("phone", staffVO.getPhone()));
        if (update) {
            return Result.OK();
        }
        return Result.Error();
    }

    /**
     * 删除员工
     *
     * @param customerIds
     * @param customerId
     * @return
     */
    @Override
    public Result delStaff(String customerIds, Integer customerId) {
        if (StrUtil.isNullOrUndefined(customerIds)) {
            return Result.Error("请求参数错误");
        }
        String[] split = customerIds.split(",");
        List<String> asList = Arrays.asList(split);
        boolean remove = removeByIds(asList);
        if (remove) {
            return Result.OK();
        }
        return Result.Error();
    }

    /**
     * 启/禁用角色
     *
     * @param customerIds
     * @param enable
     * @param customerId
     * @return
     */
    @Override
    public Result setEnable(String customerIds, Integer enable, Integer customerId) {
        if (StrUtil.isNullOrUndefined(customerIds)) {
            return Result.Error("请求参数错误");
        }
        String[] split = customerIds.split(",");
        List<String> asList = Arrays.asList(split);
        boolean update = update(new UpdateWrapper<Customer>().in("customer_id", asList).set("status", enable));
        if (update) {
            return Result.OK();
        }
        return Result.Error();
    }

    /**
     * 修改员工密码
     *
     * @param oldpassword
     * @param newPwdone
     * @param newPwdTwo
     * @param customerId
     * @return
     */
    @Override
    public Result updateStaffPw(String oldpassword, String newPwdone, String newPwdTwo, Integer customerId) {
        if (StrUtil.isNullOrUndefined(oldpassword) || StrUtil.isNullOrUndefined(oldpassword) || StrUtil.isNullOrUndefined(oldpassword)) {
            return Result.Error("请求参数异常");
        }
        if (!newPwdone.equals(newPwdTwo)) {
            return Result.Error("两次密码不一致");
        }
        Customer customer = getById(customerId);
        if (!BCrypt.checkpw(oldpassword, customer.getPassword())) {
            return Result.Error("原密码错误");
        }
        customer.setPassword(BCrypt.hashpw(newPwdone));
        boolean update = updateById(customer);
        if (update) {
            return Result.OK();
        }
        return Result.Error();
    }
}